package com.youlu.campus.admin.commission.service;

import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.admin.auth.entity.SystemUser;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.utils.IdGeneratorUtils;
import com.youlu.campus.entity.commission.DistributorAccountWithdraw;
import com.youlu.campus.entity.commission.DistributorChannel;
import com.youlu.campus.entity.commission.dto.*;
import com.youlu.campus.service.course.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : [dengbo]
 * @className : DistributorGradeService
 * @description : [渠道admin服务]
 * @createTime : [2023/2/3 13:52]
 */
@Service
@Slf4j
public class DistributorChannelAdminService {
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 虚拟商品保存
     *
     * @param saveDTO
     * @return
     */
    public boolean save(DistributorChannelSaveDTO saveDTO) {
        SystemUser systemUser = mongoTemplate.findById(saveDTO.getAccountId(), SystemUser.class);
        if (systemUser == null) {
            throw new BusinessException("账户信息不存在");
        }
        boolean isChannel = saveDTO.getChannelUser() != null && saveDTO.getChannelUser();
        if (isChannel) {
            throw new BusinessException("渠道无权限添加");
        }
        boolean save = StringUtils.isNotBlank(saveDTO.getId());
        Query query = new Query(Criteria.where("accountId").is(saveDTO.getAccountId()));
        if (save) {
            query.addCriteria(Criteria.where("id").ne(saveDTO.getId()));
        }
        DistributorChannel checkChannel = mongoTemplate.findOne(query, DistributorChannel.class);
        if (checkChannel != null) {
            throw new BusinessException("后台账户已经绑定");
        }
        if (!save) {
            DistributorChannel channel = new DistributorChannel();
            channel.setCreatedTime(new Date());
            channel.setDeleted(false);
            channel.setAccountBalance(0L);
            channel.setTotalSettlementMoney(0L);
            mongoTemplate.insert(channel);
            return true;
        }
        DistributorChannel channel = mongoTemplate.findById(saveDTO.getId(), DistributorChannel.class);
        if (channel == null) {
            throw new BusinessException("渠道信息不存在");
        }
        String userName = StringUtils.isBlank(saveDTO.getUserName()) ? systemUser.getRealName() : saveDTO.getUserName();
        Update update = new Update();
        update.set("userName", userName);
        update.set("openId", saveDTO.getOpenId());
        update.set("channelName", saveDTO.getChannelName());
        update.set("distributorRatio", saveDTO.getDistributorRatio());
        update.set("updatedTime", new Date());
        update.set("accountId", saveDTO.getAccountId());
        mongoTemplate.updateFirst(new Query(Criteria.where("id").is(saveDTO.getId())), update, DistributorChannel.class);
        return true;
    }

    public DistributorChannel getDetail(DistributorChannelDetailDTO dto) {
        DistributorChannel channel = mongoTemplate.findOne(Query.query(Criteria.where("id").is(dto.getChannelId())), DistributorChannel.class);
        return channel;
    }

    public Page<DistributorChannel> list(DistributorChannelSearchDTO dto) {
        QueryWrapper query = new QueryWrapper();
        if (dto.getChannelUser() != null && dto.getChannelUser()) {
            query.addCriteria(Criteria.where("accountId").is(dto.getAccountId()));
        }
        if (StringUtils.isNotBlank(dto.getChannelName())) {
            query.like("channelName", dto.getChannelName());
        }
        long count = mongoTemplate.count(query, DistributorChannel.class);
        query.with(Sort.by(Sort.Order.desc("createdTime")));
        PageRequest pageRequest = PageRequest.of(dto.getPage() - 1, dto.getPageSize());
        List<DistributorChannel> list = mongoTemplate.find(query.with(pageRequest), DistributorChannel.class);
        List<String> accountIdList = list.stream().map(DistributorChannel::getAccountId).distinct().collect(Collectors.toList());
        List<SystemUser> systemUsers = mongoTemplate.find(new Query(Criteria.where("id").in(accountIdList)), SystemUser.class);
        Map<String, SystemUser> map = systemUsers.stream().collect(Collectors.toMap(SystemUser::getId, Function.identity(), (o1, o2) -> o2));
        list.stream().forEach(item -> {
            SystemUser user = map.get(item.getAccountId());
            if (user != null) {
                item.setAccountName(user.getRealName());
                item.setAccountPhone(user.getMobile());
            }
        });
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    public DistributorChannel findById(String channelId) {
        return mongoTemplate.findById(channelId, DistributorChannel.class);
    }

    public DistributorChannel findByAccountId(String accountId) {
        return mongoTemplate.findOne(new Query(Criteria.where("accountId").is(accountId)), DistributorChannel.class);
    }

    public Page<DistributorAccountWithdraw> withdrawList(DistributorChannelWithdrawSearchDTO dto) {
        PageRequest pageRequest = PageRequest.of(dto.getPage() - 1, dto.getPageSize());
        if (dto.getChannelUser() != null && dto.getChannelUser()) {
            DistributorChannel channel = findByAccountId(dto.getAccountId());
            if (!channel.getId().equals(dto.getChannelId())) {
                return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0);
            }
        }
        QueryWrapper query = new QueryWrapper();
        query.addCriteria(Criteria.where("accountId").is(dto.getChannelId()));
        if (StringUtils.isNotBlank(dto.getName())) {
            query.like("name", dto.getName());
        }
        if (StringUtils.isNotBlank(dto.getMobile())) {
            query.like("mobile", dto.getMobile());
        }
        query.with(Sort.by(Sort.Order.desc("createdTime")));
        long count = mongoTemplate.count(query, DistributorAccountWithdraw.class);
        List<DistributorAccountWithdraw> list = mongoTemplate.find(query.with(pageRequest), DistributorAccountWithdraw.class);
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    public boolean channelWithdraw(DistributorChannelWithdrawDTO query) {
        if (query.getMoney() <= 0) {
            throw new BusinessException("提现金额不能小于0");
        }
        String channelId = query.getChannelId();
        DistributorChannel channel = findById(channelId);
        if (channel == null) {
            throw new BusinessException("渠道信息不存在");
        }
        if (query.getChannelUser() && !channel.getAccountId().equals(query.getAccountId())) {
            throw new BusinessException("暂无权限");
        }
        if (channel.getAccountBalance() <= 0) {
            throw new BusinessException("渠道暂无提现金额");
        }
        SystemUser systemUser = mongoTemplate.findById(channel.getAccountId(), SystemUser.class);
        if (systemUser == null) {
            throw new BusinessException("关联账户信息不存在");
        }
        if (query.getMoney() > channel.getAccountBalance()) {
            throw new BusinessException("余额不足");
        }
        Query q = new Query(Criteria.where("id").is(channelId));
        q.addCriteria(Criteria.where("accountBalance").gte(query.getMoney()));
        Update update = new Update();
        update.inc("accountBalance", -query.getMoney());
        update.set("updatedTime", new Date());
        if (StringUtils.isNotBlank(query.getBankCard())) {
            update.set("bankCard", query.getBankCard());
        }
        if (StringUtils.isNotBlank(query.getAccountsBank())) {
            update.set("accountsBank", query.getAccountsBank());
        }
        if (StringUtils.isNotBlank(query.getCompanyName())) {
            update.set("companyName", query.getCompanyName());
        }
        UpdateResult result = mongoTemplate.updateFirst(q, update, DistributorChannel.class);
        if (result.getModifiedCount() <= 0) {
            throw new BusinessException("余额不足");
        }
        DistributorAccountWithdraw withdraw = new DistributorAccountWithdraw();
        withdraw.setName(systemUser.getRealName());
        withdraw.setMobile(systemUser.getMobile());
        withdraw.setMoney(query.getMoney());
        withdraw.setOpenId(channel.getOpenId());
        withdraw.setCompanyName(query.getCompanyName());
        withdraw.setBankCard(query.getBankCard());
        withdraw.setAccountsBank(query.getAccountsBank());
        withdraw.setApplayOp(query.getOperator());
        withdraw.setChannelName(channel.getChannelName());
        // 渠道提现 类型渠道 账户id为渠道id
        withdraw.setAccountId(channelId);
        withdraw.setType(1);
        withdraw.setWithdrawType("bank-card");
        withdraw.setCreatedTime(new Date());
        String orderNo = IdGeneratorUtils.generateChannelWithdraw();
        withdraw.setOrderNo(orderNo);
        withdraw.setStatus(2);
        mongoTemplate.insert(withdraw);
        return true;
    }
}
